/**
 * 本转换流解包一个二进制PNG数据块
 * 可以被 ReadableStream 的 pipeThrough 方法消费
 */
class PNGTransformStream {
  constructor() {
    const unpacker = new PNGUnpacker();

    this.readable = new ReadableStream({
      start(controller) {
        unpacker.onChunk = chunk => controller.enqueue(chunk);
        unpacker.onClose = () => controller.close();
      }
    });

    this.writable = new WritableStream({
      write(uint8Array) {
        unpacker.addBinaryData(uint8Array);
      }
    });
  }
}

// 主流程
const tbody = document.getElementsByTagName('tbody')[0];

class LogStreamSink {
  constructor(name) {
    this.name = name;
    this.counter = 0;
  }

  write(chunk) {
    this.counter += 1;
    console.log('Chunk %d of %s: %o', this.counter, this.name, chunk);

    this.createRow(this.name, this.counter, chunk.constructor.name);
  }

  close() {
    this.createRow(this.name, this.counter, 'Closed');
  }

  createRow(heading, col1, col2) {
    const tr = document.createElement('tr');
    tbody.appendChild(tr);
    const th = document.createElement('th');
    th.appendChild(document.createTextNode(heading));
    tr.appendChild(th);
    const tdCounter = document.createElement('td');
    tdCounter.appendChild(document.createTextNode(col1));
    tr.appendChild(tdCounter);
    const tdChunk = document.createElement('td');
    tdChunk.appendChild(document.createTextNode(col2));
    tr.appendChild(tdChunk); 
  }
}

function logReadableStream(name, rs) {
  const [rs1, rs2] = rs.tee();

  rs2.pipeTo(new WritableStream(new LogStreamSink(name))).catch(console.error);

  return rs1;
}

// 获取原始图片
fetch('/images/img_1.jpg')
.then(response => response.body)
.then(rs => logReadableStream('Fetch Response Stream', rs))
.then(rs => rs.pipeThrough(new PNGTransformStream()))
.then(rs => logReadableStream('PNG Chunk Stream', rs));